﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using System.Data.SqlServerCe;

namespace Infrastructure.WpfClient.Accessibility
{
    public class AccssesibilitySyncService : Infrastructure.WpfClient.Accessibility.IAccessibilityService, IDisposable
    {


        private SqlCeConnection CeLocalConnection;
        
        public AccessibilityDataCacheSyncAgent AccessibilityAgent;

        private SqlCeCommand SelectCommand;
        private SqlCeCommand UpdateCommand;
        private SqlCeCommand InsertCommand;

        public AccssesibilitySyncService(IUnityContainer container)
        {
            this.CeLocalConnection = container.Resolve < SqlCeConnection>("CeLocalConnection");
            this.SelectCommand = new SqlCeCommand("select kind, value   from Accessibility where code=@code and code1=@code1 and code2=@code2 and application=@application and userid=@userid", this.CeLocalConnection);
            this.SelectCommand.Parameters.Add("@code", System.Data.SqlDbType.NVarChar);
            this.SelectCommand.Parameters.Add("@code1", System.Data.SqlDbType.NVarChar);
            this.SelectCommand.Parameters.Add("@code2", System.Data.SqlDbType.NVarChar);
            this.SelectCommand.Parameters.Add("@application", System.Data.SqlDbType.NVarChar);
            this.SelectCommand.Parameters.Add("@userid", System.Data.SqlDbType.UniqueIdentifier);

            this.InsertCommand = new SqlCeCommand("insert Accessibility (id, application, userid, kind, code, code1, code2, value, defaultvalue) values(@id,@application,@userid, @kind, @code,@code1,@code2,@value,@defaultvalue)", this.CeLocalConnection);
            this.InsertCommand.Parameters.Add("@id", System.Data.SqlDbType.UniqueIdentifier);
            this.InsertCommand.Parameters.Add("@application", System.Data.SqlDbType.NVarChar);
            this.InsertCommand.Parameters.Add("@userid", System.Data.SqlDbType.UniqueIdentifier);
            this.InsertCommand.Parameters.Add("@kind", System.Data.SqlDbType.NVarChar);
            this.InsertCommand.Parameters.Add("@code", System.Data.SqlDbType.NVarChar);
            this.InsertCommand.Parameters.Add("@code1", System.Data.SqlDbType.NVarChar);
            this.InsertCommand.Parameters.Add("@code2", System.Data.SqlDbType.NVarChar);
            this.InsertCommand.Parameters.Add("@value", System.Data.SqlDbType.NVarChar);
            this.InsertCommand.Parameters.Add("@defaultvalue", System.Data.SqlDbType.NVarChar);


            this.UpdateCommand = new SqlCeCommand("update Accessibility set value=@value, kind=@kind where application=@application and userid=@userid and code=@code and code1=@code1 and code2=@code2", this.CeLocalConnection);
            this.UpdateCommand.Parameters.Add("@application", System.Data.SqlDbType.NVarChar);
            this.UpdateCommand.Parameters.Add("@userid", System.Data.SqlDbType.UniqueIdentifier);
            this.UpdateCommand.Parameters.Add("@value", System.Data.SqlDbType.NVarChar);
            this.UpdateCommand.Parameters.Add("@kind", System.Data.SqlDbType.NVarChar);
            this.UpdateCommand.Parameters.Add("@code", System.Data.SqlDbType.NVarChar);
            this.UpdateCommand.Parameters.Add("@code1", System.Data.SqlDbType.NVarChar);
            this.UpdateCommand.Parameters.Add("@code2", System.Data.SqlDbType.NVarChar);

            var res = container.Resolve<string>("SqlCeConnectionString");

            this.AccessibilityAgent = new AccessibilityDataCacheSyncAgent();
            this.AccessibilityAgent.LocalProvider = container.Resolve<AccessibilityCacheClientSyncProvider>("AccessibilityClientProvider");
            this.AccessibilityAgent.RemoteProvider = container.Resolve<Microsoft.Synchronization.Data.ServerSyncProviderProxy>("AccessibilityRemoteProvider");            
            this.AccessibilityAgent.Accssebility.SyncDirection = Microsoft.Synchronization.Data.SyncDirection.Bidirectional;
            this.AccessibilityAgent.Configuration.SyncParameters.Add("CurrentUserId", Guid.Empty);

            try
            {
                var stat = this.AccessibilityAgent.Synchronize();            
            }
            catch (Exception ex)
            {
                
                throw;
            }
            
        }
        public T getSetting<T>(string application, Guid userId, string code, T defaultValue)
        {
            throw new NotImplementedException();
        }

        public T getSetting<T>(string application, Guid userId, string code, string codeone, T defaultValue)
        {
            throw new NotImplementedException();
        }


        private void validateDatabase()
        {
            if (!System.IO.File.Exists("./skynet.sdf"))
            {
                this.AccessibilityAgent.Synchronize();
            }
        }

        public T getSetting<T>(string application, Guid userId, string code, string codeone, string codetwo, T defaultValue)
        {           
            string response = "";
            string responseKind = "";
            try
            {
                validateDatabase();

                this.SelectCommand.Parameters["@application"].Value = application;
                this.SelectCommand.Parameters["@userid"].Value = userId;
                this.SelectCommand.Parameters["@code"].Value = code;
                this.SelectCommand.Parameters["@code1"].Value = codeone;
                this.SelectCommand.Parameters["@code2"].Value = codetwo; 
                
                this.CeLocalConnection.Open();

                var reader = this.SelectCommand.ExecuteReader(System.Data.CommandBehavior.SingleResult | System.Data.CommandBehavior.SingleRow);
                if (reader.Read())
                {
                    int index = reader.GetOrdinal("value");
                    if (!reader.IsDBNull(index))
                    {
                        response = reader["value"].ToString();
                        responseKind = reader["kind"].ToString();
                    }
                    else
                        response = "";
                }
                reader.Close();
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                this.CeLocalConnection.Close();
            }
            if (string.IsNullOrEmpty(response))
            {
                try
                {
                    string oresult;
                    string okind;
                    BuildStringFrom<T>(defaultValue, out oresult, out okind);
                    this.CeLocalConnection.Open();
                    this.InsertCommand.Parameters["@id"].Value = Guid.NewGuid();
                    this.InsertCommand.Parameters["@application"].Value = application;
                    this.InsertCommand.Parameters["@userid"].Value = userId;
                    this.InsertCommand.Parameters["@kind"].Value = okind;
                    this.InsertCommand.Parameters["@code"].Value = code;
                    this.InsertCommand.Parameters["@code1"].Value = codeone;
                    this.InsertCommand.Parameters["@code2"].Value = codetwo;
                    this.InsertCommand.Parameters["@value"].Value = oresult;
                    this.InsertCommand.Parameters["@defaultvalue"].Value = oresult;
                    this.InsertCommand.ExecuteNonQuery();
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    this.CeLocalConnection.Close();
                }

                return defaultValue;
            }
            else
            {
                return BuildFromString<T>(response, responseKind);
            }                      
        }

        public void setSetting<T>(string application, Guid userId, string code, T value)
        {
            throw new NotImplementedException();
        }

        public void setSetting<T>(string application, Guid userId, string code, string codeone, T value)
        {
            throw new NotImplementedException();
        }

        public void setSetting<T>(string application, Guid userId, string code, string codeone, string codetwo, T value)
        {
            string response = "";
            string responseKind = "";
            try
            {
                validateDatabase();

                this.SelectCommand.Parameters["@application"].Value = application;
                this.SelectCommand.Parameters["@userid"].Value = userId;
                this.SelectCommand.Parameters["@code"].Value = code;
                this.SelectCommand.Parameters["@code1"].Value = codeone;
                this.SelectCommand.Parameters["@code2"].Value = codetwo;

                this.CeLocalConnection.Open();

                var reader = this.SelectCommand.ExecuteReader(System.Data.CommandBehavior.SingleResult | System.Data.CommandBehavior.SingleRow);
                if (reader.Read())
                {
                    int index = reader.GetOrdinal("value");
                    if (!reader.IsDBNull(index))
                    {
                        response = reader["value"].ToString();
                        responseKind = reader["kind"].ToString();
                    }
                    else
                        response = "";
                }
                reader.Close();
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                this.CeLocalConnection.Close();
            }
            if (string.IsNullOrEmpty(response))
            {
                try
                {
                    string oresult;
                    string okind;
                    BuildStringFrom<T>(value, out oresult, out okind);
                    this.CeLocalConnection.Open();
                    this.InsertCommand.Parameters["@id"].Value = Guid.NewGuid();
                    this.InsertCommand.Parameters["@application"].Value = application;
                    this.InsertCommand.Parameters["@userid"].Value = userId;
                    this.InsertCommand.Parameters["@kind"].Value = okind;
                    this.InsertCommand.Parameters["@code"].Value = code;
                    this.InsertCommand.Parameters["@code1"].Value = codeone;
                    this.InsertCommand.Parameters["@code2"].Value = codetwo;
                    this.InsertCommand.Parameters["@value"].Value = oresult;
                    this.InsertCommand.Parameters["@defaultvalue"].Value = oresult;
                    this.InsertCommand.ExecuteNonQuery();
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    this.CeLocalConnection.Close();
                }             
            }
            else
            {
                string oresult;
                string okind;
                BuildStringFrom<T>(value, out oresult, out okind);
                if (response != oresult)
                {
                    try
                    {
                        this.CeLocalConnection.Open();                        
                        this.UpdateCommand.Parameters["@application"].Value = application;
                        this.UpdateCommand.Parameters["@userid"].Value = userId;
                        this.UpdateCommand.Parameters["@kind"].Value = okind;
                        this.UpdateCommand.Parameters["@code"].Value = code;
                        this.UpdateCommand.Parameters["@code1"].Value = codeone;
                        this.UpdateCommand.Parameters["@code2"].Value = codetwo;
                        this.UpdateCommand.Parameters["@value"].Value = oresult;                        
                        this.UpdateCommand.ExecuteNonQuery();
                    }
                    catch (Exception)
                    {

                        throw;
                    }
                    finally
                    {
                        this.CeLocalConnection.Close();
                    }
                    
                }                

            }                      
        }

        private T BuildFromString<T>(string request, string kind)
        {
            T result = default(T);
            switch (kind)
            {
                case "String":
                    result = (T)(Object)request;
                    break;
                case "Int":
                    result = (T)(Object)int.Parse(request);
                    break;
                case "Double":
                    result = (T)(Object)double.Parse(request);
                    break;
                case "Decimal":
                    result = (T)(Object)decimal.Parse(request);
                    break;
                default:
                    break;
            }
            return result;
        }
        private void BuildStringFrom<T>(T request,out string result, out string kind)        
        {
            result = "";
            kind = "na";

            if (default(T) is string)
            {
                result = request.ToString();
                kind = "String";
            }
            if (default(T) is int)
            {
                result = request.ToString();
                kind = "Int";
            }
            if (default(T) is double)
            {
                result = request.ToString();
                kind = "Double";
            }
            if (default(T) is decimal)
            {
                result = request.ToString();
                kind = "Decimal";
            }            
        }

        public void Dispose()
        {
           
        }
    }
}
